﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using MongoDB.Bson;
using MongoDB.Driver.Builders;
using eCommMongo.Core;
using eCommMongo.Core.Data;
using eCommMongo.Core.Domain.Addresses;
using eCommMongo.Core.Domain.Customers;
using eCommMongo.Core.Domain.Pictures;
using eCommMongo.Core.Domain.Shops;
using eCommMongo.Service.Pictures;

namespace eCommMongo.Service.Customers
{
    public class CustomerService:ICustomerService
    {
        private IMongoRepository<Customer> _customerRepository;
        private IMongoRepository<CustomerRole> _customerRoleRepository;
        private IPictureService _pictureService;


        public CustomerService(IMongoRepository<Customer> customerRepository, 
            IMongoRepository<CustomerRole> customerRoleRepository, 
            IPictureService pictureService)
        {
            _customerRepository = customerRepository;
            _customerRoleRepository = customerRoleRepository;
            _pictureService = pictureService;
        }

        public IPagedList<Customer> GetAllCustomers(int pageIndex, int pageSize)
        {

            var query = _customerRepository.Table();

             var tempResult = new PagedList<Customer>(query, pageIndex, pageSize);

            return tempResult;
        }

        public void UpdateCustomerShop(string customerId, string shopId)
        {
            var update = Update<Customer>.Set(e => e.Shop, new Shop{Id= shopId});
            _customerRepository.Update(customerId, update);
        }


        public void DeleteCustomer(Customer customer)
        {
            throw new System.NotImplementedException();
        }

        public Customer GetCustomerById(string customerId)
        {
            var query = from c in _customerRepository.Table()
                        where c.Id == customerId
                        select c;
            var customer = query.FirstOrDefault();
            if (customer != null)
            {

                return CustomerMapper.ToCustomer(customer);
            }
            else
            {
                return null;
            }
        }

        public Customer InsertGuestCustomer()
        {
            var customer = new Customer()
            {
                UserGuid = Guid.NewGuid(),
                Active = true,
                CreatedOn= DateTime.Now,
            };

            //add to 'Guests' role
            var guestRole = GetCustomerRoleBySystemName(SystemCustomerRoleNames.Guests);
            if (guestRole == null)
                throw new Exception("'Guests' role could not be loaded");
            customer.CustomerRoles  = new Collection<CustomerRole>();
            customer.CustomerRoles.Add(guestRole);

            _customerRepository.Insert(customer);

            return customer;
        }

        public Customer GetCustomerByUserName(string userName)
        {
            if (string.IsNullOrWhiteSpace(userName))
                return null;

            var query = from c in _customerRepository.Table()
                        orderby c.Id
                        where c.Username==userName 
                        select c;
            var customer = query.FirstOrDefault();
            if (customer != null)
            {

                return CustomerMapper.ToCustomer(customer);
            }
            else
            {
                return null;
            }
        }

        CustomerRole ICustomerService.GetCustomerRoleBySystemName(string roleName)
        {
            return GetCustomerRoleBySystemName(roleName);
        }

        public IList<CustomerRole> GetAllCustomerRoles()
        {
            return _customerRoleRepository.Table().ToList();
        }

        public void UpdateCustomerPaymentMethodSystemName(string customerId, string paymentMethodName)
        {
            var update = Update<Customer>.Set(e => e.SelectedPaymentMethodSystemName, paymentMethodName);
            _customerRepository.Update(customerId, update);
        }

        public void UpdateCustomerAddress(string customerId, ICollection<Address> addresses)
        {
            var update = Update<Customer>.Set(e => e.Addresses, addresses);
            _customerRepository.Update( customerId, update);
        }

        private CustomerRole GetCustomerRoleBySystemName(string rolename)
        {
            var query = from cr in _customerRoleRepository.Table()
                        where cr.SystemName == rolename
                        select cr;
            var customerRole = query.FirstOrDefault();
            return customerRole;
        }

        public IList<Customer> GetAllNotUsedShopOwners()
        {
            throw new System.NotImplementedException();
        }

        public void UpdateCustomerSelectedShippingAddress(string customerId, Address shippingAddress)
        {
            var update = Update<Customer>.Set(e => e.ShippingAddress, shippingAddress);
            _customerRepository.Update(customerId, update);
        }

        public void UpdateCustomerLogo(string customerId, string pictureId)
        {
            var customerLogo = new CustomerLogo()
                {
                    //Picture = _pictureService.GetPictureById(pictureId),
                    Picture = new Picture(){Id = pictureId},
                    DisplayOrder = 0
                };


            var update = Update<Customer>.Set(e => e.CustomerLogo, customerLogo);

            _customerRepository.Update(customerId, update);
        }

       

        public void UpdateCustomerInfo(string customerId, string nickName, string intro)
        {
            var cust = _customerRepository.GetById(customerId);

            cust.NickName = nickName;
            cust.Intro = intro;

            var update = Update<Customer>.Set(e => e.NickName, nickName).Set(e=>e.Intro, intro);

            _customerRepository.Update(customerId, update);

        }

        public void UpdateCustomer(Customer customer)
        {
            if (customer == null)
                throw new ArgumentNullException("customer");

            //var cust = _customerRepository.GetById(EntityNames.Customers, customer.Id);
            //cust.Addresses.Clear();
            //foreach (var ad in customer.Addresses)
            //{
            //    cust.Addresses.Add(_addressRepository.GetById(ad.Id));
            //}

            //cust.CustomerRoles.Clear();
            //foreach (var cr in customer.CustomerRoles)
            //{
            //    cust.CustomerRoles.Add(_customerRoleRepository.GetById(cr.Id));
            //}

            //if (customer.ShippingAddress != null)
            //{
            //    cust.ShippingAddress = _addressRepository.GetById(customer.ShippingAddress.Id);
            //}

            //cust.SelectedPaymentMethodSystemName = customer.SelectedPaymentMethodSystemName;
            //cust.Username = customer.Username;
            //cust.Email = customer.Email;
            //cust.Password = customer.Password;
            //cust.Active = customer.Active;
            //cust.ShopId = customer.ShopId;
            
            _customerRepository.Save( customer);
        }

        public Customer GetCustomerByEmail(string usernameOrEmail)
        {
            if (string.IsNullOrWhiteSpace(usernameOrEmail))
                return null;

            var query = from c in _customerRepository.Table()
                        where c.Email == usernameOrEmail
                        select c;
            var customers = query.ToList();
            if (customers != null && customers.Count>0)
            {

                var customer = customers[0];
                return CustomerMapper.ToCustomer(customer);
            }
            else
            {
                return null;
            }

           
        }

       
       
       

       

        public Customer GetUserByGuid(Guid customerGuid)
        {
            var query = from c in _customerRepository.Table()
                        where c.UserGuid ==customerGuid 
                        select c;
            var customer = query.FirstOrDefault();
            if (customer != null)
            {

                return CustomerMapper.ToCustomer(customer);
            }
            else
            {
                return null;
            }
        }
    }
}